//! 完整的API服务器实现

use std::sync::Arc;
use axum::{
    routing::{get, post, delete, put},
    http::StatusCode,
    response::{IntoResponse, Json},
    Router,
    extract::{Query, State},
};
use axum::serve;
use tower_http::cors::{CorsLayer, Any};
use tower_http::trace::TraceLayer;
use tracing::{info, error};
use tokio::sync::RwLock;

use nacos_core::traits::{NamingService, ConfigService};
use crate::cluster_adapter::ClusterIntegrationManager;
use crate::server::ServerState;
use super::{ApiConfig, ApiResponse};

/// 完整的API服务器
pub struct ApiServer {
    config: ApiConfig,
    naming_service: Arc<dyn NamingService>,
    config_service: Arc<dyn ConfigService>,
    cluster_integration: Arc<ClusterIntegrationManager>,
    server_state: Arc<RwLock<ServerState>>,
    server_handle: Option<tokio::task::JoinHandle<()>>,
}

impl ApiServer {
    pub fn new(
        config: ApiConfig,
        naming_service: Arc<dyn NamingService>,
        config_service: Arc<dyn ConfigService>,
        cluster_integration: Arc<ClusterIntegrationManager>,
        server_state: Arc<RwLock<ServerState>>,
    ) -> Self {
        Self {
            config,
            naming_service,
            config_service,
            cluster_integration,
            server_state,
            server_handle: None,
        }
    }

    /// 启动API服务器
    pub async fn start(&mut self,
    ) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
        let addr = format!("0.0.0.0:{}", self.config.rest_port);
        info!("启动REST API服务器: {}", addr);

        let app = self.create_router();

        let listener = tokio::net::TcpListener::bind(&addr).await?;
        let server = serve(listener, app.into_make_service());

        info!("REST API服务器启动成功: {}", addr);

        let handle = tokio::spawn(async move {
            if let Err(e) = server.await {
                error!("API服务器错误: {}", e);
            }
        });

        self.server_handle = Some(handle);

        Ok(())
    }

    /// 停止API服务器
    pub async fn stop(&mut self) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
        info!("停止API服务器");
        
        if let Some(handle) = self.server_handle.take() {
            handle.abort();
        }

        Ok(())
    }

    /// 创建路由
    fn create_router(&self,
    ) -> Router {
        let cors = if self.config.cors_enabled {
            CorsLayer::new()
                .allow_origin(Any)
                .allow_methods(Any)
                .allow_headers(Any)
        } else {
            CorsLayer::new()
        };

        Router::new()
            // 健康检查
            .route("/health", get(health_check))
            .route("/nacos/v1/console/health/readiness", get(readiness_health_check))
            .route("/nacos/v1/ns/instance", post(register_instance))
            .route("/nacos/v1/ns/instance", delete(deregister_instance))
            .route("/nacos/v1/ns/instance", put(modify_instance))
            .route("/nacos/v1/ns/instance/beat", put(handle_heartbeat))
            .route("/nacos/v1/ns/instance/list", get(get_instances))
            .route("/nacos/v1/ns/service/list", get(list_services))
            // 配置服务API
            .route("/nacos/v1/cs/configs", post(publish_config))
            .route("/nacos/v1/cs/configs", get(get_config))
            .route("/nacos/v1/cs/configs", delete(delete_config))
            // 集群管理API
            .route("/nacos/v1/cluster/status", get(get_cluster_status))
            .route("/nacos/v1/cluster/nodes", get(get_cluster_nodes))
            .route("/nacos/v1/cluster/nodes", post(add_cluster_node))
            .route("/nacos/v1/cluster/nodes", delete(remove_cluster_node))
            // 共享状态
            .with_state(AppState {
                naming_service: self.naming_service.clone(),
                config_service: self.config_service.clone(),
                cluster_integration: self.cluster_integration.clone(),
                server_state: self.server_state.clone(),
            })
            .layer(cors)
            .layer(TraceLayer::new_for_http())
    }
}

/// 应用状态
#[derive(Clone)]
struct AppState {
    naming_service: Arc<dyn NamingService>,
    config_service: Arc<dyn ConfigService>,
    cluster_integration: Arc<ClusterIntegrationManager>,
    server_state: Arc<RwLock<ServerState>>,
}

/// 健康检查
async fn health_check() -> Json<ApiResponse<String>> {
    Json(ApiResponse::success("OK".to_string()))
}

/// 健康检查
async fn readiness_health_check(
    State(state): State<AppState>,
) -> (StatusCode, Json<serde_json::Value>) {
    let server_state = *state.server_state.read().await;
    if server_state == ServerState::Running {
        (StatusCode::OK, Json(serde_json::json!({ "status": "UP" })))
    } else {
        (StatusCode::SERVICE_UNAVAILABLE, Json(serde_json::json!({ "status": "DOWN" })))
    }
}

/// 命名服务处理器

#[derive(serde::Deserialize)]
struct RegisterInstanceRequest {
    namespace: Option<String>,
    serviceName: String,
    ip: String,
    port: u16,
    weight: Option<f32>,
    healthy: Option<bool>,
    enabled: Option<bool>,
    ephemeral: Option<bool>,
    clusterName: Option<String>,
    metadata: Option<std::collections::HashMap<String, String>>,
}

async fn register_instance(
    State(state): State<AppState>,
    Query(payload): Query<RegisterInstanceRequest>,
) -> Result<String, (StatusCode, String)> {
    use nacos_core::ServiceInstance;
    let namespace = payload.namespace.as_deref().unwrap_or("public");

    let mut instance = ServiceInstance::new(
        payload.serviceName.clone(),
        "DEFAULT_GROUP".to_string(),
        payload.ip.clone(),
        payload.port,
    );
    instance.namespace = namespace.to_string();
    instance.weight = payload.weight.unwrap_or(1.0) as f64;
    instance.healthy = payload.healthy.unwrap_or(true);
    instance.enabled = payload.enabled.unwrap_or(true);
    instance.ephemeral = payload.ephemeral.unwrap_or(true);
    if let Some(cluster_name) = payload.clusterName {
        instance.cluster_name = cluster_name;
    }
    instance.metadata = payload.metadata.unwrap_or_default();

    state.naming_service
        .register_instance(&instance)
        .await
        .map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()))?;

    // 官方Nacos API返回 "ok" 字符串
    Ok("ok".to_string())
}

#[derive(serde::Deserialize)]
struct DeregisterInstanceRequest {
    namespace: Option<String>,
    serviceName: String,
    ip: String,
    port: u16,
}

async fn deregister_instance(
    State(state): State<AppState>,
    Query(payload): Query<DeregisterInstanceRequest>,
) -> Result<String, (StatusCode, String)> {
    let namespace = payload.namespace.as_deref().unwrap_or("public");
    // 构建实例ID：namespace#group#service_name#instance_id 格式
    let instance_id = format!("{}#{}#{}#{}:{}", 
        namespace, 
        "DEFAULT_GROUP", 
        payload.serviceName, 
        payload.ip, 
        payload.port
    );
    
    state.naming_service
        .deregister_instance(namespace, "DEFAULT_GROUP", &payload.serviceName, &instance_id)
        .await
        .map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()))?;

    Ok("ok".to_string())
}

#[derive(serde::Deserialize)]
struct ModifyInstanceRequest {
    namespace: Option<String>,
    serviceName: String,
    ip: String,
    port: u16,
    weight: Option<f32>,
    healthy: Option<bool>,
    enabled: Option<bool>,
    ephemeral: Option<bool>,
    clusterName: Option<String>,
    metadata: Option<std::collections::HashMap<String, String>>,
}

async fn modify_instance(
    State(state): State<AppState>,
    Query(payload): Query<ModifyInstanceRequest>,
) -> Result<String, (StatusCode, String)> {
    use nacos_core::ServiceInstance;
    let namespace = payload.namespace.as_deref().unwrap_or("public");

    let mut instance = ServiceInstance::new(
        payload.serviceName.clone(),
        "DEFAULT_GROUP".to_string(),
        payload.ip.clone(),
        payload.port,
    );
    instance.namespace = namespace.to_string();
    instance.weight = payload.weight.unwrap_or(1.0) as f64;
    instance.healthy = payload.healthy.unwrap_or(true);
    instance.enabled = payload.enabled.unwrap_or(true);
    instance.ephemeral = payload.ephemeral.unwrap_or(true);
    if let Some(cluster_name) = payload.clusterName {
        instance.cluster_name = cluster_name;
    }
    instance.metadata = payload.metadata.unwrap_or_default();

    state.naming_service
        .update_instance(&instance)
        .await
        .map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()))?;

    Ok("ok".to_string())
}

#[derive(serde::Deserialize)]
struct GetInstancesRequest {
    namespace: Option<String>,
    serviceName: String,
    healthyOnly: Option<bool>,
}

// Nacos官方API格式的实例列表响应
#[derive(serde::Serialize)]
struct NacosInstanceListResponse {
    pub hosts: Vec<NacosInstance>,
    pub dom: String,
    pub name: String,
    pub cacheMillis: u64,
    pub lastRefTime: u64,
    pub checksum: String,
    pub allIPs: bool,
    pub reachProtectionThreshold: bool,
    pub valid: bool,
}

#[derive(serde::Serialize)]
struct NacosInstance {
    pub instanceId: String,
    pub ip: String,
    pub port: u16,
    pub weight: f64,
    pub healthy: bool,
    pub enabled: bool,
    pub ephemeral: bool,
    pub clusterName: String,
    pub serviceName: String,
    pub metadata: std::collections::HashMap<String, String>,
    pub instanceHeartBeatInterval: u64,
    pub instanceHeartBeatTimeOut: u64,
    pub ipDeleteTimeout: u64,
    pub instanceIdGenerator: String,
}

async fn get_instances(
    State(state): State<AppState>,
    Query(params): Query<GetInstancesRequest>,
) -> Result<Json<NacosInstanceListResponse>, (StatusCode, String)> {
    let namespace = params.namespace.as_deref().unwrap_or("public");
    let instances = if params.healthyOnly.unwrap_or(true) {
        state.naming_service
            .get_healthy_instances(namespace, "DEFAULT_GROUP", &params.serviceName)
            .await
            .map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()))?
    } else {
        state.naming_service
            .get_all_instances(namespace, "DEFAULT_GROUP", &params.serviceName)
            .await
            .map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()))?
    };

    // 转换为Nacos官方格式
    let nacos_instances: Vec<NacosInstance> = instances.into_iter().map(|instance| {
        NacosInstance {
            instanceId: instance.instance_id,
            ip: instance.ip,
            port: instance.port,
            weight: instance.weight,
            healthy: instance.healthy,
            enabled: instance.enabled,
            ephemeral: instance.ephemeral,
            clusterName: instance.cluster_name,
            serviceName: instance.service_name,
            metadata: instance.metadata,
            instanceHeartBeatInterval: 5000,
            instanceHeartBeatTimeOut: 15000,
            ipDeleteTimeout: 30000,
            instanceIdGenerator: "simple".to_string(),
        }
    }).collect();

    let response = NacosInstanceListResponse {
        hosts: nacos_instances,
        dom: params.serviceName.clone(),
        name: params.serviceName,
        cacheMillis: 10000,
        lastRefTime: chrono::Utc::now().timestamp_millis() as u64,
        checksum: "".to_string(),
        allIPs: false,
        reachProtectionThreshold: false,
        valid: true,
    };

    Ok(Json(response))
}

#[derive(serde::Deserialize)]
struct ListServicesRequest {
    namespace: Option<String>,
    page: Option<u32>,
    pageSize: Option<u32>,
}

// Nacos官方服务列表响应格式
#[derive(serde::Serialize)]
struct NacosServiceListResponse {
    pub doms: Vec<String>,
    pub count: u32,
}

async fn list_services(
    State(state): State<AppState>,
    Query(params): Query<ListServicesRequest>,
) -> Result<Json<NacosServiceListResponse>, (StatusCode, String)> {
    let namespace = params.namespace.as_deref().unwrap_or("public");
    let services = state.naming_service
        .get_all_service_names(namespace, Some("DEFAULT_GROUP"))
        .await
        .map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()))?;

    let response = NacosServiceListResponse {
        count: services.len() as u32,
        doms: services,
    };

    Ok(Json(response))
}


#[derive(serde::Deserialize)]
struct HandleHeartbeatRequest {
    namespace: Option<String>,
    serviceName: String,
    ip: String,
    port: u16,
}

async fn handle_heartbeat(
    State(state): State<AppState>,
    Query(payload): Query<HandleHeartbeatRequest>,
) -> Result<String, (StatusCode, String)> {
    let namespace = payload.namespace.as_deref().unwrap_or("public");
    let instance_id = format!("{}#{}#{}#{}:{}", 
        namespace, 
        "DEFAULT_GROUP", 
        payload.serviceName, 
        payload.ip, 
        payload.port
    );

    state.naming_service
        .handle_heartbeat(namespace, "DEFAULT_GROUP", &payload.serviceName, &instance_id)
        .await
        .map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()))?;

    // 官方Nacos心跳API返回 "ok" 字符串
    Ok("ok".to_string())
}

/// 配置服务处理器

#[derive(serde::Deserialize)]
struct PublishConfigRequest {
    namespace: Option<String>,
    group: Option<String>,
    dataId: String,
    content: String,
    tenant: Option<String>,
}

async fn publish_config(
    State(state): State<AppState>,
    Query(payload): Query<PublishConfigRequest>,
) -> Result<String, (StatusCode, String)> {
    // 处理参数默认值
    let namespace = payload.tenant.as_deref().or(payload.namespace.as_deref()).unwrap_or("public");
    let group = payload.group.as_deref().unwrap_or("DEFAULT_GROUP");
    
    let result = state.config_service
        .publish_config(namespace, group, &payload.dataId, &payload.content)
        .await
        .map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()))?;

    // 官方Nacos API返回 "true" 或 "false" 字符串
    Ok(result.to_string())
}

#[derive(serde::Deserialize)]
struct GetConfigRequest {
    namespace: Option<String>,
    group: Option<String>,
    dataId: String,
    tenant: Option<String>, // Nacos中的namespace通常叫做tenant
}

async fn get_config(
    State(state): State<AppState>,
    Query(params): Query<GetConfigRequest>,
) -> Result<String, (StatusCode, String)> {
    // 处理参数默认值
    let namespace = params.tenant.as_deref().or(params.namespace.as_deref()).unwrap_or("public");
    let group = params.group.as_deref().unwrap_or("DEFAULT_GROUP");
    
    let config_content = state.config_service
        .get_config(namespace, group, &params.dataId)
        .await
        .map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()))?
        .ok_or((StatusCode::NOT_FOUND, "配置不存在".to_string()))?;

    // 官方Nacos API直接返回配置内容字符串
    Ok(config_content)
}

#[derive(serde::Deserialize)]
struct DeleteConfigRequest {
    namespace: Option<String>,
    group: Option<String>,
    dataId: String,
    tenant: Option<String>,
}

async fn delete_config(
    State(state): State<AppState>,
    Query(payload): Query<DeleteConfigRequest>,
) -> Result<String, (StatusCode, String)> {
    // 处理参数默认值
    let namespace = payload.tenant.as_deref().or(payload.namespace.as_deref()).unwrap_or("public");
    let group = payload.group.as_deref().unwrap_or("DEFAULT_GROUP");
    
    let result = state.config_service
        .remove_config(namespace, group, &payload.dataId)
        .await
        .map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()))?;

    // 官方Nacos API返回 "true" 或 "false" 字符串
    Ok(result.to_string())
}

/// 集群管理处理器

async fn get_cluster_status(
    State(state): State<AppState>,
) -> Result<Json<ApiResponse<crate::cluster_adapter::ClusterStatus>>, (StatusCode, String)> {
    let status = state.cluster_integration
        .get_cluster_status()
        .await
        .map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()))?;

    Ok(Json(ApiResponse::success(status)))
}

async fn get_cluster_nodes(
    State(state): State<AppState>,
) -> Result<Json<ApiResponse<Vec<nacos_core::ClusterNode>>>, (StatusCode, String)> {
    let nodes = state.cluster_integration.get_cluster_nodes().await
        .map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()))?;

    Ok(Json(ApiResponse::success(nodes)))
}

#[derive(serde::Deserialize)]
struct AddClusterNodeRequest {
    node: nacos_core::ClusterNode,
}

async fn add_cluster_node(
    State(state): State<AppState>,
    Json(payload): Json<AddClusterNodeRequest>,
) -> Result<Json<ApiResponse<()>>, (StatusCode, String)> {
    state.cluster_integration
        .add_cluster_node(payload.node)
        .await
        .map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()))?;

    Ok(Json(ApiResponse::success(())))
}

#[derive(serde::Deserialize)]
struct RemoveClusterNodeRequest {
    node_id: String,
}

async fn remove_cluster_node(
    State(state): State<AppState>,
    Json(payload): Json<RemoveClusterNodeRequest>,
) -> Result<Json<ApiResponse<()>>, (StatusCode, String)> {
    state.cluster_integration
        .remove_cluster_node(&payload.node_id)
        .await
        .map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()))?;

    Ok(Json(ApiResponse::success(())))
}

#[cfg(test)]
mod tests {
    use super::*;
    use axum::{
        body::Body,
        http::{Request, StatusCode},
    };
    use tower::ServiceExt;

    #[tokio::test]
    async fn test_health_check() {
        // 创建一个简单的路由来测试健康检查端点
        let app = Router::new().route("/health", get(super::health_check));

        let response = app
            .oneshot(Request::builder()
                .uri("/health")
                .body(Body::empty())
                .unwrap())
            .await
            .unwrap();

        assert_eq!(response.status(), StatusCode::OK);
    }
}
